package com.school.sports.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.school.sports.entity.Enrollment;
import com.school.sports.entity.User;
import com.school.sports.service.EnrollmentService;
import com.school.sports.common.Result;
import lombok.extern.slf4j.Slf4j;
import javax.validation.Valid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.Arrays;
import java.util.List;

/**
 * 报名管理控制器
 * 提供报名的增删改查、审核等功能
 */
@Slf4j
@RestController
@RequestMapping("/api/enrollments")
public class EnrollmentController {

    @Autowired
    private EnrollmentService enrollmentService;

    /**
     * 分页查询报名列表
     * @param currentPage 当前页码
     * @param pageSize 每页大小
     * @param userId 用户ID
     * @param projectId 项目ID
     * @param status 报名状态
     * @param realName 学生姓名（模糊查询）
     * @param projectName 项目名称（模糊查询）
     * @return 分页结果
     */
    @GetMapping("/page/{currentPage}/{pageSize}")
    @PreAuthorize("hasAnyRole('管理员', '老师')")
    public Result<IPage<Enrollment>> getEnrollmentPage(
            @PathVariable("currentPage") Integer currentPage,
            @PathVariable("pageSize") Integer pageSize,
            @RequestParam(value = "userId", required = false) Long userId,
            @RequestParam(value = "projectId", required = false) Long projectId,
            @RequestParam(value = "status", required = false) String status,
            @RequestParam(value = "realName", required = false) String realName,
            @RequestParam(value = "projectName", required = false) String projectName) {

        log.info("分页查询报名列表，当前页码：{}，每页条数：{}，查询条件：userId={}, projectId={}, status={}, realName={}, projectName={}",
                currentPage, pageSize, userId, projectId, status, realName, projectName);

        try {
            Page<Enrollment> page = new Page<>(currentPage, pageSize);
            LambdaQueryWrapper<Enrollment> queryWrapper = new LambdaQueryWrapper<>();

            // 构建查询条件
            queryWrapper.eq(userId != null, Enrollment::getUserId, userId)
                    .eq(projectId != null, Enrollment::getProjectId, projectId)
                    .eq(StringUtils.hasText(status), Enrollment::getStatus, status)
                    .orderByDesc(Enrollment::getCreatedAt);

            IPage<Enrollment> enrollmentPage = enrollmentService.page(page, queryWrapper);
            log.info("查询报名列表成功，共{}条记录", enrollmentPage.getTotal());
            return Result.success(enrollmentPage);
        } catch (Exception e) {
            log.error("查询报名列表异常：{}", e.getMessage(), e);
            return Result.fail("查询失败：" + e.getMessage());
        }
    }

    /**
     * 根据ID查询报名详情
     * @param enrollmentId 报名ID
     * @return 报名详情
     */
    @GetMapping("/{enrollmentId}")
    @PreAuthorize("hasAnyRole('管理员', '老师', '学生')")
    public Result<Enrollment> getEnrollmentById(@PathVariable("enrollmentId") Long enrollmentId) {
        log.info("查询报名详情，报名ID：{}", enrollmentId);

        if (enrollmentId == null || enrollmentId <= 0) {
            return Result.fail("报名ID无效");
        }

        try {
            Enrollment enrollment = enrollmentService.getEnrollmentWithDetails(enrollmentId);
            if (enrollment == null) {
                return Result.fail("报名不存在");
            }
            log.info("查询报名详情成功，报名ID：{}", enrollmentId);
            return Result.success(enrollment);
        } catch (Exception e) {
            log.error("查询报名详情异常：{}", e.getMessage(), e);
            return Result.fail("查询失败：" + e.getMessage());
        }
    }

    /**
     * 学生报名项目
     * @param enrollment 报名信息
     * @return 操作结果
     */
    @PostMapping
    @PreAuthorize("hasRole('学生')")
    public Result<String> enrollProject(@Valid @RequestBody Enrollment enrollment) {
        log.info("学生报名项目：{}", enrollment.getProjectId());

        try {
            // 获取当前用户
            User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();

            boolean success = enrollmentService.enrollProject(
                    currentUser.getId(),
                    enrollment.getProjectId(),
                    enrollment.getHealthStatement()
            );

            if (success) {
                log.info("报名成功，用户ID：{}，项目ID：{}", currentUser.getId(), enrollment.getProjectId());
                return Result.success("报名成功，请等待审核");
            } else {
                return Result.fail("报名失败，请检查项目状态或是否已报名");
            }
        } catch (Exception e) {
            log.error("报名异常：{}", e.getMessage(), e);
            return Result.fail("报名失败：" + e.getMessage());
        }
    }

    /**
     * 学生取消报名
     * @param enrollmentId 报名ID
     * @return 操作结果
     */
    @DeleteMapping("/{enrollmentId}")
    @PreAuthorize("hasRole('学生')")
    public Result<String> cancelEnrollment(@PathVariable("enrollmentId") Long enrollmentId) {
        log.info("取消报名，报名ID：{}", enrollmentId);

        if (enrollmentId == null || enrollmentId <= 0) {
            return Result.fail("报名ID无效");
        }

        try {
            // 获取当前用户
            User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();

            boolean success = enrollmentService.cancelEnrollment(enrollmentId, currentUser.getId());
            if (success) {
                log.info("取消报名成功，报名ID：{}", enrollmentId);
                return Result.success("取消报名成功");
            } else {
                return Result.fail("取消报名失败，请检查报名状态");
            }
        } catch (Exception e) {
            log.error("取消报名异常：{}", e.getMessage(), e);
            return Result.fail("取消报名失败：" + e.getMessage());
        }
    }

    /**
     * 审核报名
     * @param enrollmentId 报名ID
     * @param status 审核结果
     * @param rejectReason 驳回原因
     * @return 操作结果
     */
    @PutMapping("/{enrollmentId}/audit")
    @PreAuthorize("hasAnyRole('管理员', '老师')")
    public Result<String> auditEnrollment(
            @PathVariable("enrollmentId") Long enrollmentId,
            @RequestParam("status") String status,
            @RequestParam(value = "rejectReason", required = false) String rejectReason) {

        log.info("审核报名，报名ID：{}，审核结果：{}，驳回原因：{}", enrollmentId, status, rejectReason);

        if (enrollmentId == null || enrollmentId <= 0) {
            return Result.fail("报名ID无效");
        }

        if (!isValidStatus(status)) {
            return Result.fail("审核结果不合法");
        }

        if ("已驳回".equals(status) && !StringUtils.hasText(rejectReason)) {
            return Result.fail("驳回时必须提供驳回原因");
        }

        try {
            boolean success = enrollmentService.auditEnrollment(enrollmentId, status, rejectReason);
            if (success) {
                log.info("审核报名成功，报名ID：{}", enrollmentId);
                return Result.success("审核成功");
            } else {
                return Result.fail("审核失败，请检查报名状态");
            }
        } catch (Exception e) {
            log.error("审核报名异常：{}", e.getMessage(), e);
            return Result.fail("审核失败：" + e.getMessage());
        }
    }

    /**
     * 批量审核报名
     * @param enrollmentIds 报名ID列表
     * @param status 审核结果
     * @param rejectReason 驳回原因
     * @return 操作结果
     */
    @PutMapping("/batch-audit")
    @PreAuthorize("hasAnyRole('管理员', '老师')")
    public Result<String> batchAuditEnrollments(
            @RequestBody List<Long> enrollmentIds,
            @RequestParam("status") String status,
            @RequestParam(value = "rejectReason", required = false) String rejectReason) {

        log.info("批量审核报名，报名ID列表：{}，审核结果：{}", enrollmentIds, status);

        if (enrollmentIds == null || enrollmentIds.isEmpty()) {
            return Result.fail("请选择要审核的报名记录");
        }

        if (!isValidStatus(status)) {
            return Result.fail("审核结果不合法");
        }

        if ("已驳回".equals(status) && !StringUtils.hasText(rejectReason)) {
            return Result.fail("驳回时必须提供驳回原因");
        }

        try {
            boolean success = enrollmentService.batchAuditEnrollment(enrollmentIds, status, rejectReason);
            if (success) {
                log.info("批量审核报名成功，共{}条记录", enrollmentIds.size());
                return Result.success("批量审核成功");
            } else {
                return Result.fail("批量审核部分失败");
            }
        } catch (Exception e) {
            log.error("批量审核报名异常：{}", e.getMessage(), e);
            return Result.fail("批量审核失败：" + e.getMessage());
        }
    }

    /**
     * 根据用户ID查询报名列表
     * @param userId 用户ID
     * @return 报名列表
     */
    @GetMapping("/user/{userId}")
    @PreAuthorize("hasAnyRole('管理员', '老师', '学生')")
    public Result<List<Enrollment>> getEnrollmentsByUserId(@PathVariable("userId") Long userId) {
        log.info("根据用户ID查询报名列表，用户ID：{}", userId);

        if (userId == null || userId <= 0) {
            return Result.fail("用户ID无效");
        }

        try {
            List<Enrollment> enrollments = enrollmentService.getEnrollmentsByUserId(userId);
            log.info("查询报名列表成功，共{}条记录", enrollments.size());
            return Result.success(enrollments);
        } catch (Exception e) {
            log.error("查询报名列表异常：{}", e.getMessage(), e);
            return Result.fail("查询失败：" + e.getMessage());
        }
    }

    /**
     * 根据项目ID查询报名列表
     * @param projectId 项目ID
     * @return 报名列表
     */
    @GetMapping("/project/{projectId}")
    @PreAuthorize("hasAnyRole('管理员', '老师')")
    public Result<List<Enrollment>> getEnrollmentsByProjectId(@PathVariable("projectId") Long projectId) {
        log.info("根据项目ID查询报名列表，项目ID：{}", projectId);

        if (projectId == null || projectId <= 0) {
            return Result.fail("项目ID无效");
        }

        try {
            List<Enrollment> enrollments = enrollmentService.getEnrollmentsByProjectId(projectId);
            log.info("查询报名列表成功，共{}条记录", enrollments.size());
            return Result.success(enrollments);
        } catch (Exception e) {
            log.error("查询报名列表异常：{}", e.getMessage(), e);
            return Result.fail("查询失败：" + e.getMessage());
        }
    }

    /**
     * 获取报名状态列表
     * @return 报名状态列表
     */
    @GetMapping("/statuses")
    @PreAuthorize("hasAnyRole('管理员', '老师', '学生')")
    public Result<List<String>> getEnrollmentStatuses() {
        log.info("获取报名状态列表");
        try {
            List<String> statuses = enrollmentService.getAllEnrollmentStatuses();
            log.info("获取报名状态列表成功，共{}种状态", statuses.size());
            return Result.success(statuses);
        } catch (Exception e) {
            log.error("获取报名状态列表异常：{}", e.getMessage(), e);
            return Result.fail("获取失败：" + e.getMessage());
        }
    }

    /**
     * 根据状态查询报名列表
     * @param status 报名状态
     * @return 报名列表
     */
    @GetMapping("/status/{status}")
    @PreAuthorize("hasAnyRole('管理员', '老师')")
    public Result<List<Enrollment>> getEnrollmentsByStatus(@PathVariable("status") String status) {
        log.info("根据状态查询报名列表，状态：{}", status);

        if (!StringUtils.hasText(status)) {
            return Result.fail("状态参数不能为空");
        }

        try {
            List<Enrollment> enrollments = enrollmentService.getEnrollmentsByStatus(status);
            log.info("查询报名列表成功，共{}条记录", enrollments.size());
            return Result.success(enrollments);
        } catch (Exception e) {
            log.error("查询报名列表异常：{}", e.getMessage(), e);
            return Result.fail("查询失败：" + e.getMessage());
        }
    }

    /**
     * 检查用户是否已报名某项目
     * @param userId 用户ID
     * @param projectId 项目ID
     * @return 检查结果
     */
    @GetMapping("/check-enrollment")
    @PreAuthorize("hasAnyRole('管理员', '老师', '学生')")
    public Result<Boolean> checkUserEnrollment(
            @RequestParam("userId") Long userId,
            @RequestParam("projectId") Long projectId) {
        log.info("检查用户报名状态，用户ID：{}，项目ID：{}", userId, projectId);

        try {
            boolean isEnrolled = enrollmentService.isUserEnrolled(userId, projectId);
            return Result.success(isEnrolled);
        } catch (Exception e) {
            log.error("检查用户报名状态异常：{}", e.getMessage(), e);
            return Result.fail("检查失败：" + e.getMessage());
        }
    }

    /**
     * 统计某项目的报名人数
     * @param projectId 项目ID
     * @return 报名人数
     */
    @GetMapping("/count/project/{projectId}")
    @PreAuthorize("hasAnyRole('管理员', '老师')")
    public Result<Long> countEnrollmentsByProjectId(@PathVariable("projectId") Long projectId) {
        log.info("统计项目报名人数，项目ID：{}", projectId);

        try {
            long count = enrollmentService.countEnrollmentsByProjectId(projectId);
            return Result.success(count);
        } catch (Exception e) {
            log.error("统计项目报名人数异常：{}", e.getMessage(), e);
            return Result.fail("统计失败：" + e.getMessage());
        }
    }

    /**
     * 校验状态合法性
     */
    private boolean isValidStatus(String status) {
        return "待审核".equals(status) || "已通过".equals(status)
                || "已驳回".equals(status) || "已取消".equals(status);
    }
}